package com.competition.prediction.service.impl;

import com.competition.prediction.dto.PlaceBetDTO;
import com.competition.prediction.entity.Competition;
import com.competition.prediction.entity.User;
import com.competition.prediction.entity.UserBet;
import com.competition.prediction.mapper.CompetitionMapper;
import com.competition.prediction.mapper.UserBetMapper;
import com.competition.prediction.mapper.UserMapper;
import com.competition.prediction.service.BettingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
public class BettingServiceImpl implements BettingService {

    @Autowired
    private UserBetMapper userBetMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private CompetitionMapper competitionMapper;

    @Override
    @Transactional
    public boolean placeBet(Long userId, PlaceBetDTO placeBetDTO) {
        User user = userMapper.selectUserById(userId);
        if (user == null || user.getCoins() < placeBetDTO.getBetAmount()) {
            throw new RuntimeException("用户硬币不足");
        }

        Competition competition = competitionMapper.selectCompetitionById(placeBetDTO.getCompetitionId());
        if (competition == null || competition.getStatus() != 1) {
            throw new RuntimeException("比赛不存在或已结束");
        }

        if (LocalDateTime.now().isAfter(competition.getBetDeadline())) {
            throw new RuntimeException("投注已截止");
        }

        UserBet userBet = new UserBet();
        userBet.setUserId(userId);
        userBet.setCompetitionId(placeBetDTO.getCompetitionId());
        userBet.setBetOptionId(placeBetDTO.getBetOptionId());
        userBet.setBetAmount(placeBetDTO.getBetAmount());
        userBet.setPotentialReturn(placeBetDTO.getBetAmount() * 2L);
        userBet.setStatus(1);
        userBet.setBetTime(LocalDateTime.now());

        if (userBetMapper.insertUserBet(userBet) > 0) {
            userMapper.updateUserCoins(userId, user.getCoins() - placeBetDTO.getBetAmount());
            return true;
        }
        return false;
    }

    @Override
    public List<UserBet> getUserBets(Long userId) {
        return userBetMapper.selectUserBetsByUserId(userId);
    }

    @Override
    @Transactional
    public boolean settleBet(Long competitionId, Integer result) {
        List<UserBet> bets = userBetMapper.selectUserBetsByCompetitionId(competitionId);
        for (UserBet bet : bets) {
            if (bet.getStatus() == 1) {
                boolean isWin = (result == 1 && bet.getBetOptionId().equals(1L)) ||
                              (result == 2 && bet.getBetOptionId().equals(2L));

                if (isWin) {
                    Long actualReturn = bet.getPotentialReturn();
                    userBetMapper.updateBetStatus(bet.getId(), 2, actualReturn);

                    User user = userMapper.selectUserById(bet.getUserId());
                    userMapper.updateUserCoins(bet.getUserId(), user.getCoins() + actualReturn);
                } else {
                    userBetMapper.updateBetStatus(bet.getId(), 3, 0L);
                }
            }
        }
        return true;
    }
}